home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Code Resources / 3D Buttons CDEF 1.0b4 / Source / 3D Buttons CDEF source / (3D Buttons CDEF.π) / LGBCheckbox.cp < prev    next >
Encoding:
Text File  |  1994-07-31  |  11.7 KB  |  442 lines  |  [TEXT/MMCC]

  1. /**************************************************************************
  2.     LGBCheckbox
  3.     
  4.     Public domain, by Zig Zichterman.
  5.     
  6.     This class implements 3D checkboxes according to the guidelines
  7.     suggested in _develop_ 15. Some of the drawing code is taken from
  8.     the public domain source accompanying _develop_ 15.
  9.  
  10.         07/31/94    zz    Draw 3D if 4-bit grey, BW if 4-bit color
  11.         07/31/94    zz    save/restore pen colors
  12.     1.0b3
  13.         07/28/94    zz    offscreen drawing for less flashy TextBox()
  14.     1.0b2 (never released)
  15.         07/20/94    zz    call PenNormal() before drawing anything!
  16.     1.0b1
  17. **************************************************************************/
  18. #include "LGBCheckbox.h"
  19.  
  20. #include <GestaltEqu.h>
  21.  
  22. #include "LGBControl.h"
  23. #include "LGBDeviceIterator.h"
  24. #include "UGBDraw.h"
  25.  
  26. const short    LGBCheckbox_boxWidth    = 12;
  27.  
  28. /**************************************************************************
  29.     Main()                                                        [static]
  30.     
  31.     Main entry point for all checkbox calls. Dispatch according to
  32.     message.
  33. **************************************************************************/
  34. long
  35. LGBCheckbox::Main(short inVariation, ControlHandle ioControl,
  36.         short inMsg, long ioParam)
  37. {
  38.     long            returnMe    = 0;
  39.  
  40.     // lock the control handle for the duration of this call
  41.     char state = ::HGetState((Handle) ioControl);
  42.     ::HLock((Handle) ioControl);
  43.     
  44.     LGBCheckbox    checkbox(*ioControl,(inVariation & useWFont)?true:false);
  45.     
  46.     switch (inMsg) {
  47.         case drawCntl    :
  48.                 checkbox.Draw(ioParam);
  49.                 break;
  50.                             
  51.         case testCntl    :
  52.             {
  53.                 Point    hitPt;
  54.                 hitPt.h    = LoWord(ioParam);
  55.                 hitPt.v    = HiWord(ioParam);
  56.                 if (checkbox.Test(hitPt)) {
  57.                     returnMe = inButton;
  58.                 }
  59.             }
  60.             break;
  61.         
  62.         case calcCRgns    :    // only called in 24-bit mode
  63.             {    // is 32-bit addressing off?
  64.                 long    result    = 0;
  65.                 OSErr    err = ::Gestalt(gestaltAddressingModeAttr,&result);
  66.                 if (!err && ((result &
  67.                         (1L << gestalt32BitAddressing)) == 0)) {
  68.                     RgnHandle    rgn = (RgnHandle)
  69.                                     ::StripAddress((Ptr) ioParam);
  70.                     checkbox.CalcCRgn(rgn);
  71.                 }
  72.             }
  73.             break;
  74.         
  75.         case calcCntlRgn    :    // only called in 32-bit mode
  76.             checkbox.CalcCRgn((RgnHandle) ioParam);
  77.             break;
  78.     }
  79.     
  80.     // unlock handle
  81.     ::HSetState((Handle) ioControl,state);
  82.     return returnMe;
  83. }
  84.  
  85. //—————————————————————————————————————————————————————————————————————————
  86. // Constructor
  87. //—————————————————————————————————————————————————————————————————————————
  88.  
  89. /**************************************************************************
  90.     LGBCheckbox(ControlHandle,Boolean)
  91.     
  92.     construct/initialize a control object. Just stores the control handle
  93.     and the "should I use the window font?" flag in data members.
  94. **************************************************************************/
  95. LGBCheckbox::LGBCheckbox(ControlRecord *inControl, Boolean inUseWFont)
  96.     : mControl(inControl), mUseWFont(inUseWFont)
  97. {
  98.  
  99. }
  100.  
  101. //—————————————————————————————————————————————————————————————————————————
  102. // Dispatch entry points
  103. //—————————————————————————————————————————————————————————————————————————
  104.  
  105. /**************************************************************************
  106.     Draw()
  107.     
  108.     Draw the control. inPartCode is a part code specifying which part of
  109.     the control to draw, or 0 for the entire control.
  110.     
  111.     Checkboxes only have inButton, so we ignore the inPartCode.
  112.  
  113.     Save the current drawing environment. Iterate through all the devices
  114.     (screens), drawing the control in color or black and white depending
  115.     on the screen depth. Once done, restore the drawing environment and
  116.     return.
  117. **************************************************************************/
  118. void
  119. LGBCheckbox::Draw(long inPartCode)
  120. {
  121.     // if we're invisible, don't draw
  122.     if (mControl->contrlVis == false) return;
  123.     
  124.     // save the font
  125.     short    font,size,mode,face;
  126.     {
  127.         GrafPtr    port;
  128.         ::GetPort(&port);
  129.         font    = port->txFont;
  130.         size    = port->txSize;
  131.         mode    = port->txMode;
  132.         face    = port->txFace;
  133.     }
  134.  
  135.     // save the pen colors        // will probably crash SEs, so test first
  136.     RGBColor    fore,back;
  137.     if (UGBDraw::ColorQDIsPresent()) {
  138.         ::GetForeColor(&fore);
  139.         ::GetBackColor(&back);
  140.     }
  141.  
  142.     // save the clip region
  143.     RgnHandle    saveClip    = ::NewRgn();
  144.     if (!saveClip) return;
  145.     ::GetClip(saveClip);
  146.  
  147.     // make the pen something sensible
  148.     ::PenNormal();
  149.     ::ForeColor(blackColor);
  150.     ::BackColor(whiteColor);
  151.     
  152.     // loop through all the devices (screens)
  153.     UGBDraw::Offscreen    offscreen;
  154.     LGBDeviceIterator    device;
  155.     device.Init(mControl->contrlRect);
  156.     short    depth    = 0;
  157.     do {
  158.         depth = device.Next();
  159.         if (depth == 0) break;    // all done with devices
  160.         UGBDraw::OffscreenPre(offscreen);
  161.         if ((depth < 4)
  162.                 || (depth == 4 && device.mDeviceIsColor)) {
  163.             DrawBW();
  164.         } else {
  165.             DrawColor();
  166.         }
  167.         UGBDraw::OffscreenPost(offscreen);
  168.     } while(true);
  169.  
  170.     // restore the clip region
  171.     ::SetClip(saveClip);
  172.     ::DisposeRgn(saveClip);
  173.     
  174.     // restore the pen
  175.     if (UGBDraw::ColorQDIsPresent()) {
  176.         ::RGBForeColor(&fore);
  177.         ::RGBBackColor(&back);
  178.     }
  179.  
  180.     // restore the font
  181.     ::TextFont(font);
  182.     ::TextSize(size);
  183.     ::TextMode(mode);
  184.     ::TextFace(face);
  185. }
  186.  
  187. /**************************************************************************
  188.     Test()
  189.     
  190.     Return inButton if the point is in our rect
  191. **************************************************************************/
  192. Boolean
  193. LGBCheckbox::Test(Point inHitPt)
  194. {
  195.     return ::PtInRect(inHitPt,&(mControl->contrlRect));
  196. }
  197.  
  198. /**************************************************************************
  199.     CalcCRgn()
  200.     
  201.     Calculate the control's region in the given region handle.
  202.     The region is just our bounding rect.
  203. **************************************************************************/
  204. void
  205. LGBCheckbox::CalcCRgn(RgnHandle ioRgn)
  206. {
  207.     if (!ioRgn) return;        // idiot resistance
  208.     ::RectRgn(ioRgn,&(mControl->contrlRect));
  209. }
  210.  
  211. //—————————————————————————————————————————————————————————————————————————
  212. // Draw
  213. //—————————————————————————————————————————————————————————————————————————
  214.  
  215. /**************************************************************************
  216.     DrawBW()
  217.     
  218.     Draw the control in black and white. It is NOT safe to make any
  219.     color QuickDraw calls here.
  220. **************************************************************************/
  221. void
  222. LGBCheckbox::DrawBW(void)
  223. {
  224.     // Set the pen to black, 1x1
  225.     ::PenNormal();
  226.  
  227.     // set up our font
  228.     if (!mUseWFont) LGBControl::SetupFont();
  229.     
  230.     // calculate box locations
  231.     Rect    checkbox,titleBox;
  232.     CalcBoxes(checkbox,titleBox);
  233.     
  234.     // draw the parts
  235.     DrawCheckbox(checkbox);
  236.     DrawTitle(titleBox, mControl->contrlHilite == 255);
  237. }
  238.  
  239. /**************************************************************************
  240.     DrawColor()
  241.     
  242.     Draw the control in color
  243. **************************************************************************/
  244. void
  245. LGBCheckbox::DrawColor(void)
  246. {
  247.     // draw active or inactive?
  248.     if (mControl->contrlHilite == 255) {
  249.         DrawColorInactive();
  250.     } else {
  251.         DrawColorActive();
  252.     }
  253.  
  254.     // restore the pen
  255.     ::PenNormal();
  256.     UGBDraw::PenReallyNormal();
  257. }
  258.  
  259. /**************************************************************************
  260.     CalcBoxes()
  261.     
  262.     Figure out where to draw the checkbox and the title.
  263. **************************************************************************/
  264. void
  265. LGBCheckbox::CalcBoxes(Rect &outCheckbox, Rect &outTitleBox)
  266. {
  267.     const Rect    contrlRect    = mControl->contrlRect;
  268.     const StringPtr    title    = mControl->contrlTitle;
  269.     LGBControl::CalcBoxes(contrlRect,title,
  270.                     outCheckbox,outTitleBox);
  271. }
  272.  
  273. /**************************************************************************
  274.     DrawCheckbox()
  275.     
  276.     Draw the checkbox. Draw the 3D effect, the "X", everything
  277.     but the title and the background.
  278. **************************************************************************/
  279. void
  280. LGBCheckbox::DrawCheckbox(const Rect &inCheckbox,Boolean inColor)
  281. {
  282.     // draw the frame
  283.     ::FrameRect(&inCheckbox);
  284.     
  285.     // draw the X or erase the guts
  286.     const short value = mControl->contrlValue;
  287.     if (value <= 1) {            // erase the insides unless tristated
  288.         Rect    eraseMe;
  289.         eraseMe.top        = inCheckbox.top + 1;
  290.         eraseMe.left    = inCheckbox.left + 1;
  291.         eraseMe.right    = inCheckbox.right - 1;
  292.         eraseMe.bottom    = inCheckbox.bottom - 1;
  293.         ::EraseRect(&eraseMe);
  294.     }
  295.     if (value == 0) {            // clear checkbox
  296.         // do nothing
  297.     } else if (value == 1) {    // X
  298.         Rect    x;
  299.         x.left        = inCheckbox.left;
  300.         x.top        = inCheckbox.top;
  301.         x.right        = inCheckbox.right - 1;
  302.         x.bottom    = inCheckbox.bottom - 1;
  303.         ::MoveTo(x.left,x.top);
  304.         ::LineTo(x.right,x.bottom);
  305.         ::MoveTo(x.left,x.bottom);
  306.         ::LineTo(x.right,x.top);
  307.     } else if (value == 2) {    // tristate
  308.         // fabricate a ltGray pattern on the fly. We don't
  309.         // have quickdraw globals and I'm not going to set
  310.         // up A4 to get them.
  311.         unsigned char ltGrey[8];
  312.         ltGrey[0] = ltGrey[2] = ltGrey[4] = ltGrey[6] = 0x88;
  313.         ltGrey[1] = ltGrey[3] = ltGrey[5] = ltGrey[7] = 0x22;
  314.         
  315.         if (inColor) {
  316.             // draw a greyish pattern, not black on white
  317.             UGBDraw::ForeGrey(UGBDraw_grey7);
  318.             UGBDraw::BackGrey(UGBDraw_greyD);
  319.         }
  320.         Rect    grayRect = inCheckbox;
  321.         ::InsetRect(&grayRect,1,1);
  322.         ::FillRect(&grayRect,(PatPtr) <Grey);
  323.         if (inColor) {
  324.             UGBDraw::PenNormal();
  325.         }
  326.     }
  327.     
  328.     // draw highlight
  329.     if ((mControl->contrlHilite)
  330.             && (mControl->contrlHilite != 255)) {
  331.         ::PenNormal();
  332.         Rect    hilite = inCheckbox;
  333.         ::InsetRect(&hilite,1,1);
  334.         ::FrameRect(&hilite);
  335.     }
  336. }
  337.  
  338. /**************************************************************************
  339.     DrawTitle()
  340.     
  341.     Draw the title.
  342. **************************************************************************/
  343. void
  344. LGBCheckbox::DrawTitle(const Rect &inTitleBox, Boolean inDim1Bit)
  345. {
  346.     const StringPtr    title = mControl->contrlTitle;
  347.     ::TextBox(title + 1,*title,&inTitleBox,teFlushDefault);
  348.     
  349.     // grey out the name if inactive
  350.     if (inDim1Bit) {
  351.         unsigned char grey[8];
  352.         grey[0] = grey[2] = grey[4] = grey[6] = 0xAA;
  353.         grey[1] = grey[3] = grey[5] = grey[7] = 0x55;
  354.         ::PenPat((PatPtr) grey);
  355.         ::PenMode(patBic);
  356.         ::PaintRect(&inTitleBox);
  357.         ::PenNormal();
  358.     }
  359. }
  360.  
  361. /**************************************************************************
  362.     DrawColorInactive()
  363.     
  364.     Draw the checkbox, in color, but flattened out and inactive
  365. **************************************************************************/
  366. void
  367. LGBCheckbox::DrawColorInactive(void)
  368. {
  369.     // Set the pen to black, 1x1
  370.     ::PenNormal();
  371.     
  372.     // set up our font
  373.     if (!mUseWFont) LGBControl::SetupFont();
  374.     
  375.     // calculate box locations
  376.     Rect    checkbox,titleBox;
  377.     CalcBoxes(checkbox,titleBox);
  378.     
  379.     // grey out our entire background
  380.     UGBDraw::Background();
  381.     ::EraseRect(&(mControl->contrlRect));
  382.     
  383.     // set the pen to the "inactive control" color
  384.     // set the backcolor to white
  385.     UGBDraw::PenFrameInactive();
  386.     UGBDraw::BackGrey(UGBDraw_greyF);
  387.     DrawCheckbox(checkbox,true);
  388.     
  389.     // draw the button title
  390.     // set the background to grey
  391.     UGBDraw::Background();
  392.     DrawTitle(titleBox);
  393. }
  394.  
  395. /**************************************************************************
  396.     DrawColorActive()
  397.     
  398.     Draw the checkbox, in 3D color
  399. **************************************************************************/
  400. void
  401. LGBCheckbox::DrawColorActive(void)
  402. {
  403.     // Set the pen to black, 1x1
  404.     ::PenNormal();
  405.     
  406.     
  407.     // set up our font
  408.     if (!mUseWFont) LGBControl::SetupFont();
  409.     
  410.     // calculate box locations
  411.     Rect    checkbox,titleBox;
  412.     CalcBoxes(checkbox,titleBox);
  413.     
  414.     // grey out our entire background
  415.     UGBDraw::Background();
  416.     ::EraseRect(&(mControl->contrlRect));
  417.     
  418.     // set the pen to the "active control" color
  419.     // set the backcolor to white
  420.     UGBDraw::PenFrameActive();
  421.     UGBDraw::BackGrey(UGBDraw_greyF);
  422.     DrawCheckbox(checkbox,true);
  423.     
  424.     // draw the button title
  425.     // set the background to grey
  426.     UGBDraw::Background();
  427.     DrawTitle(titleBox, mControl->contrlHilite == 255);
  428.     
  429.     // draw 3D effect around checkbox
  430.         // top left sides
  431.     UGBDraw::ForeGrey(UGBDraw_greyA);
  432.     ::MoveTo(checkbox.left - 1,checkbox.bottom);
  433.     ::LineTo(checkbox.left - 1,checkbox.top - 1);
  434.     ::LineTo(checkbox.right,checkbox.top - 1);
  435.     
  436.         // bottom right sides
  437.     UGBDraw::ForeGrey(UGBDraw_greyF);
  438.     ::MoveTo(checkbox.left,checkbox.bottom);
  439.     ::LineTo(checkbox.right,checkbox.bottom);
  440.     ::LineTo(checkbox.right,checkbox.top);
  441. }
  442.